//
// CDVInputFilters.cpp
//

/*-----------------------------------------------------*\
			HQ Tech, Make Technology Easy!       
 More information, please go to http://hqtech.nease.net.
/*-----------------------------------------------------*/

#include "stdafx.h"
#include "CDVInputFilters.h"

#include "CDXFilter.h"
#include "CDVCaptureFilter.h"
#include "CLiveCapture.h"
#include "CSmartTeeFilter.h"
#include "UDsUtils.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

////////////////////////////////////////////////////////////////////////
CDVInputFilters::CDVInputFilters(CDXGraph * inGraph) :
CLiveInputFilters(inGraph)
{
	mDVCapture		= NULL;
	mDVSplitter		= NULL;
	mDVVideoDecoder = NULL;
}

CDVInputFilters::~CDVInputFilters()
{
	Release();
}

BOOL CDVInputFilters::Create(void)
{
	ASSERT(mGraph);
	ASSERT(mLiveCapture);

	HRESULT hr = S_OK;
	mDVCapture = new CDVCaptureFilter(mGraph->GetGraph(), 
		mLiveCapture->GetVideoDevice());
	mSmartTee  = new CSmartTeeFilter(mGraph->GetGraph());
	mDVSplitter = new CDXFilter(mGraph->GetGraph(), CLSID_DVSplitter,
		"DV Splitter");
	mDVVideoDecoder = new CDXFilter(mGraph->GetGraph(), CLSID_DVVideoCodec,
		"DV Video Decoder");

	BOOL pass = CLiveInputFilters::Create();
	if (pass)
	{
		pass = mDVCapture->CreateFilter();
	}
	if (pass)
	{
		// Create other DV related filters
		pass = mDVSplitter->CreateFilter();
		pass = mDVVideoDecoder->CreateFilter();
	}
	if (pass)
	{
		// Connect filters
		IPin * pOut = mDVCapture->GetAVOutputPin();
		IPin * pIn  = mDVSplitter->GetPin(TRUE);
		pass = mGraph->ConnectFilters(pOut, pIn);

		pOut = mDVSplitter->GetPin(FALSE, "DVVidOut0");
		pIn  = mDVVideoDecoder->GetPin(TRUE);
		pass = mGraph->ConnectFilters(pOut, pIn);
	}
	if (pass)
	{
		AdjustOutput();
		CheckSmartTee();
	}

	return pass;
}

void CDVInputFilters::Release(void)
{
	SAFE_DELETE(mSmartTee);
	SAFE_DELETE(mDVSplitter);
	SAFE_DELETE(mDVVideoDecoder);
	SAFE_DELETE(mDVCapture);	
}

BOOL CDVInputFilters::IsFieldPicture(void)
{
	return TRUE;
}

IPin * CDVInputFilters::GetVideoOutPin(void)
{
	// Check smart tee first
	if (mSmartTee && mSmartTee->GetFilter())
	{
		return mSmartTee->GetCapturePin();
	}

	if (mDVVideoDecoder->GetFilter())
	{
		return mDVVideoDecoder->GetPin(FALSE);
	}
	return NULL;
}

IPin * CDVInputFilters::GetPreviewPin(void)
{
	// Check smart tee first
	if (mSmartTee && mSmartTee->GetFilter())
	{
		return mSmartTee->GetPreviewPin();
	}

	if (mDVVideoDecoder->GetFilter())
	{
		return mDVVideoDecoder->GetPin(FALSE);
	}
	return NULL;
}

IPin * CDVInputFilters::GetAudioOutPin(void)
{
	if (mDVSplitter->GetFilter())
	{
		return mDVSplitter->GetPin(FALSE, "AudOut00");
	}
	return NULL;
}

void CDVInputFilters::ShowVideoCapturePropertyPage(void)
{
	UDsUtils::ShowFilterPropertyPage(mDVCapture->GetFilter());
}

BOOL CDVInputFilters::IsActiveDeviceLost(IUnknown * pLost)
{
	if (mDVCapture && mDVCapture->GetFilter())
	{
		IUnknown * pDevice = NULL;
		mDVCapture->GetFilter()->QueryInterface(IID_IUnknown, (void**)&pDevice);
		pDevice->Release();
		if (::IsEqualObject(pDevice, pLost))
		{
			return TRUE;
		}
	}

	return FALSE;
}

// DV video decoder only provides 4 kinds of image size:
// DVRESOLUTION_FULL, DVRESOLUTION_HALF, 
// DVRESOLUTION_QUARTER, DVRESOLUTION_DC
void CDVInputFilters::AdjustOutput(void)
{
	_DVRESOLUTION dvResolution;
	long width = 0, height = 0;
	mLiveCapture->GetImageSize(&width, &height);
	if (width >= 720)
	{
		dvResolution = DVRESOLUTION_FULL;
	}
	else if (width < 720 && width >= 360)
	{
		dvResolution = DVRESOLUTION_HALF;
	}
	else if (width < 360 && width >= 180)
	{
		dvResolution = DVRESOLUTION_QUARTER;
	}
	else
	{
		dvResolution = DVRESOLUTION_DC;
	}

	IBaseFilter * pFilter = mDVVideoDecoder->GetFilter();
	if (pFilter)
	{
		IIPDVDec *  pIPDVDec = NULL; 
		pFilter->QueryInterface(IID_IIPDVDec, (void**)&pIPDVDec);
		if (pIPDVDec)
		{
			pIPDVDec->Release();
			pIPDVDec->put_IPDisplay(dvResolution);
		}
	}	
}

// When capture mode, we should insert a smart tee
void CDVInputFilters::CheckSmartTee(void)
{
	if (mLiveCapture->GetWorkMode() == MD_Capture)
	{
		BOOL pass = mSmartTee->CreateFilter();
		if (pass && mDVVideoDecoder->GetFilter())
		{
			IPin * pOut = mDVVideoDecoder->GetPin(FALSE);
			IPin * pIn  = mSmartTee->GetInputPin();
			pass = mGraph->ConnectFilters(pOut, pIn);
		}
	}
}